// Copyright 2016 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef V8_COMPILER_BACKEND_ARM_UNWINDING_INFO_WRITER_ARM_H_
#define V8_COMPILER_BACKEND_ARM_UNWINDING_INFO_WRITER_ARM_H_

#include "src/eh-frame.h"
#include "src/flags.h"

namespace v8 {
namespace internal {
    namespace compiler {

        class InstructionBlock;

        class UnwindingInfoWriter {
        public:
            explicit UnwindingInfoWriter(Zone* zone)
                : zone_(zone)
                , eh_frame_writer_(zone)
                , saved_lr_(false)
                , block_will_exit_(false)
                , block_initial_states_(zone)
            {
                if (enabled())
                    eh_frame_writer_.Initialize();
            }

            void SetNumberOfInstructionBlocks(int number)
            {
                if (enabled())
                    block_initial_states_.resize(number);
            }

            void BeginInstructionBlock(int pc_offset, const InstructionBlock* block);
            void EndInstructionBlock(const InstructionBlock* block);

            void MarkLinkRegisterOnTopOfStack(int pc_offset);
            void MarkPopLinkRegisterFromTopOfStack(int pc_offset);

            void MarkFrameConstructed(int at_pc);
            void MarkFrameDeconstructed(int at_pc);

            void MarkBlockWillExit() { block_will_exit_ = true; }

            void Finish(int code_size)
            {
                if (enabled())
                    eh_frame_writer_.Finish(code_size);
            }

            EhFrameWriter* eh_frame_writer()
            {
                return enabled() ? &eh_frame_writer_ : nullptr;
            }

        private:
            bool enabled() const { return FLAG_perf_prof_unwinding_info; }

            class BlockInitialState : public ZoneObject {
            public:
                explicit BlockInitialState(bool saved_lr)
                    : saved_lr_(saved_lr)
                {
                }

                bool saved_lr_;
            };

            Zone* zone_;
            EhFrameWriter eh_frame_writer_;
            bool saved_lr_;
            bool block_will_exit_;

            ZoneVector<const BlockInitialState*> block_initial_states_;
        };

    } // namespace compiler
} // namespace internal
} // namespace v8

#endif // V8_COMPILER_BACKEND_ARM_UNWINDING_INFO_WRITER_ARM_H_
